package main

import "fmt"

// 作业1：求n的阶乘。至少使用递归函数完成一次。

// 循环解法
func factorial1(n int) int {
	product := 1
	for i := 1; i <= n; i++ {
		product = product * i
	}
	return product
}

// 递归公式解法
func factorial2(n int) int {
	if n == 1 {
		return 1
	}
	return n * factorial1(n-1)
}

// 循环层次变成递归函数层次
func factorial3(n, product, i int) int {
	if n == 1 {
		return product
	}
	i++
	// 在递归的同时做循环计算，当递归到最后一层时，直接返回循环计算结果
	return factorial3(n-1, product*i, i)
}

// 作业2：编写一个函数，接受一个参数n，n为正整数。要求数字必须对齐。
func upper_triangle(n int) {
	for i := 1; i <= n; i++ {
		for j := n; j >= 1; j-- {
			if j > i {
				// 确认和数字相关的占位空格个数，然后按照个数打印空格
				for k := 1; k <= j/10+1; k++ {
					fmt.Print(" ")
				}
				// 打印所需占位空格后，必须保持间隔的1个空格
				fmt.Print(" ")
			} else {
				// 实际打印出的数字和间隔空格
				fmt.Printf("%d ", j)
			}
		}
		fmt.Println()
	}
}

// 作业3：简述defer作用和应用
// 解答：
// 1，作用：在某函数中使用defer语句，会使得defer后跟语句进行延迟处理，当该函数即将返
// 回时，或发生panic时，defer后的语句开始执行。os.Exit不是这两种情况，不会执行defer。
// 执行的先后顺序和注册的顺序正好相反，也就是后注册的先执行。
// 2，应用：资源释放。例如文件打开后要关闭、网络连接后要断开、获得锁用完后的释放等
// 以上场景中，获得资源后紧跟着写defer语句，以确保函数正常退出或panic时，能够释放资源。

func main() {
	// 作业1
	fmt.Printf("6的阶乘结果（使用循环）是：%d\n", factorial1(6))
	fmt.Printf("6的阶乘结果（使用递归）是：%d\n", factorial2(6))
	fmt.Printf("6的阶乘结果（使用循环+递归）是：%d\n", factorial3(6, 1, 1))
	fmt.Println("-----------------------------")
	// 作业2
	upper_triangle(12)
}
